package com.google.gwt.vector.client.ui;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.ClickListenerCollection;
import com.google.gwt.user.client.ui.LoadListener;
import com.google.gwt.user.client.ui.LoadListenerCollection;
import com.google.gwt.user.client.ui.MouseListener;
import com.google.gwt.user.client.ui.MouseListenerCollection;
import com.google.gwt.user.client.ui.SourcesClickEvents;
import com.google.gwt.user.client.ui.SourcesLoadEvents;
import com.google.gwt.user.client.ui.SourcesMouseEvents;
import com.google.gwt.vector.client.Vector;

/**
 * A general class for Vector based widgets
 */
public abstract class BasicShape extends VectorWidget implements SourcesClickEvents,
SourcesMouseEvents, SourcesLoadEvents {

  private ClickListenerCollection clickListeners = null;

  private LoadListenerCollection loadListeners = null;

  private MouseListenerCollection mouseListeners = null;;

  private Fill fill = null;
  private Stroke stroke = null;

  protected BasicShape(Element elem) {
    super(elem);
    sinkEvents(Event.ONCLICK | Event.MOUSEEVENTS | Event.ONLOAD | Event.ONERROR);
    if (Vector.isVml()) {
      fill = new Fill();
      add(fill);
      stroke = new Stroke();
      add(stroke);
    }
  }

  public void addClickListener(ClickListener listener) {
    if (clickListeners == null) {
      clickListeners = new ClickListenerCollection();
    }
    clickListeners.add(listener);
  }

  public void addLoadListener(LoadListener listener) {
    if (loadListeners == null) {
      loadListeners = new LoadListenerCollection();
    }
    loadListeners.add(listener);
  }

  public void addMouseListener(MouseListener listener) {
    if (mouseListeners == null) {
      mouseListeners = new MouseListenerCollection();
    }
    mouseListeners.add(listener);
  }

  public void onBrowserEvent(Event event) {
    switch (DOM.eventGetType(event)) {
      case Event.ONCLICK: {
        if (clickListeners != null) {
          clickListeners.fireClick(this);
        }
        break;
      }
      case Event.ONMOUSEDOWN:
      case Event.ONMOUSEUP:
      case Event.ONMOUSEMOVE:
      case Event.ONMOUSEOVER:
      case Event.ONMOUSEOUT: {
        if (mouseListeners != null) {
          mouseListeners.fireMouseEvent(this, event);
        }
        break;
      }
      case Event.ONLOAD: {
        if (loadListeners != null) {
          loadListeners.fireLoad(this);
        }
        break;
      }
      case Event.ONERROR: {
        if (loadListeners != null) {
          loadListeners.fireError(this);
        }
        break;
      }
    }
  }

  public void removeClickListener(ClickListener listener) {
    if (clickListeners != null) {
      clickListeners.remove(listener);
    }
  }

  public void removeLoadListener(LoadListener listener) {
    if (loadListeners != null) {
      loadListeners.remove(listener);
    }
  }

  public void removeMouseListener(MouseListener listener) {
    if (mouseListeners != null) {
      mouseListeners.remove(listener);
    }
  }

  public void setColor(Color color) {
    if (fill == null) {
      Vector.setColor(getElement(), color.getHexValue());
    } else {
      Vector.setColor(fill, color.getHexValue());
    }
  }

  public void setOpacity(double opality) {
    if (fill == null) {
      Vector.setOpacity(getElement(), opality);
    } else {
      Vector.setOpacity(fill, opality);
    }
  }

  public void setStrokeColor(Color color) {
    if (fill == null) {
      Vector.setStrokeColor(getElement(), color.getHexValue());
    } else {
      Vector.setStrokeColor(stroke, color.getHexValue());
    }
  }

  public void setStrokeOpacity(double opacity) {
    if (fill == null) {
      Vector.setStrokeOpacity(getElement(), opacity);
    } else {
      Vector.setStrokeOpacity(stroke, opacity);
    }
  }

  public void setStrokeWidth(double width) {
    if (fill == null) {
      Vector.setStrokeWidth(getElement(), width);
    } else {
      Vector.setStrokeWidth(stroke, width);
    }
  }

  /**
   * VML specific element.
   *
   */
  public class Fill extends VectorWidget {

    private Fill(Element elem) {
      super(elem);
    }
    private Fill() {
      this(Vector.createFill());
    }
  }
  /**
   * VML specific element.
   *
   */
  public class Stroke extends VectorWidget {

    private Stroke(Element elem) {
      super(elem);
    }
    private Stroke() {
      this(Vector.createStroke());
    }
  }
}
